package org.nahtanoj.contacts;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Locale;
import java.util.logging.Logger;

import com.google.api.client.util.Base64;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.contacts.ContactEntry;
import com.google.gdata.data.contacts.ContactGroupEntry;
import com.google.gdata.data.contacts.Event;
import com.google.gdata.data.contacts.GroupMembershipInfo;
import com.google.gdata.data.extensions.City;
import com.google.gdata.data.extensions.Country;
import com.google.gdata.data.extensions.Email;
import com.google.gdata.data.extensions.ExtendedProperty;
import com.google.gdata.data.extensions.FamilyName;
import com.google.gdata.data.extensions.FullName;
import com.google.gdata.data.extensions.GivenName;
import com.google.gdata.data.extensions.Name;
import com.google.gdata.data.extensions.PhoneNumber;
import com.google.gdata.data.extensions.PostCode;
import com.google.gdata.data.extensions.Region;
import com.google.gdata.data.extensions.Street;
import com.google.gdata.data.extensions.StructuredPostalAddress;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;

public class Contact {
	private static final String EP_CHILDREN = "CHILDREN";
	private static final String EP_CONTACTSYNC = "SYNC";
	private static final String EP_HASH = "HASH";
	private static final String EP_NOTES = "NOTES";
	private static final Logger log = Logger.getLogger(Contact.class.getName());
	private static final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
	private String anniversary;
	private String birthday;
	private String business;
	private String category;
	private String children;
	private String contactSync;
	private String email2Address;
	private String emailAddress;
	private String firstName;
	private String hash;
	private String home;
	private String homeCity;
	private String homeCountry;
	private String homePostalCode;
	private String homeState;
	private String homeStreet;
	private String homeStreet2;
	private String lastName;

	private String mobile;
	private String mobile2;
	private String notes;

	// Spreadsheet fields
	private int row;
	private String validation;

	// Docs fields
	private ContactEntry ce;
	private ContactGroupEntry g;
	private ContactGroupEntry myContacts;//systemGroups.get("System Group: My Contacts")
	private Contact match;

	public Contact(ContactGroupEntry cg, ContactEntry ce) {
		initFromContactEntry(ce);
		if (cg != null && cg.getTitle() != null) {
			this.category = cg.getTitle().getPlainText();
		}
		if (this.category != null) { // Strip off the System Group: part
			if (this.category.startsWith("System Group: ")) {
				this.category = this.category.substring(this.category.indexOf(": ") + 2);
			}
		}
		this.g = cg;
	}

	public Contact(ContactEntry ce) {
		initFromContactEntry(ce);
	}

	private void initFromContactEntry(ContactEntry ce) {
		if (ce.getName() != null) {
			if (ce.getName().getFamilyName() != null) {
				this.lastName = ce.getName().getFamilyName().getValue();
			}
			if (ce.getName().getGivenName() != null) {
				this.firstName = ce.getName().getGivenName().getValue();
			}
		}

		for (PhoneNumber p : ce.getPhoneNumbers()) {
			if (p.getRel().equals("http://schemas.google.com/g/2005#home")) {
				this.home = p.getPhoneNumber();
			} else {
				if (p.getRel().equals("http://schemas.google.com/g/2005#work")) {
					this.business = p.getPhoneNumber();
				} else {
					if (p.getRel().equals("http://schemas.google.com/g/2005#mobile")) {
						if (this.mobile == null) {
							this.mobile = p.getPhoneNumber();
						} else {
							if (this.mobile2 == null) {
								this.mobile2 = p.getPhoneNumber();
							} else {
								log.warning("More than 2 mobile numbers:" + this.lastName + " " + this.mobile);
							}
						}
					} else {
						log.warning("Unknown schema:" + p.getRel() + " " + p.getPhoneNumber() + " " + p.getLabel() + " " + p.getPrimary());
					}
				}
			}
		}

		for (Email e : ce.getEmailAddresses()) {
			if (e.getRel() != null) {
				if (e.getRel().equals("http://schemas.google.com/g/2005#home")) {
					if (this.emailAddress == null) {
						this.emailAddress = e.getAddress();
					} else {
						if (this.email2Address == null) {
							this.email2Address = e.getAddress();
						} else {
							log.warning("More than two email addresses:" + this.lastName + " " + this.emailAddress);
						}
					}
				} else {
					if (e.getRel().equals("http://schemas.google.com/g/2005#other") ||
							e.getRel().equals("http://schemas.google.com/g/2005#work")) {
						if (this.email2Address == null) {
							this.email2Address = e.getAddress();
						} else {
							if (this.emailAddress == null) {
								this.emailAddress = e.getAddress();
							} else {
								log.warning("More than two email addresses:" + this.lastName + " " + this.emailAddress);
							}
						}
					} else {
						log.warning("Unknown email schema:" + e.getRel() + " " + e.getAddress() + " " + e.getLabel() + " " + e.getPrimary());
					}
				}
			}
		}

		for (StructuredPostalAddress p : ce.getStructuredPostalAddresses()) {
			if (p.getPrimary() == true || p.getRel().equals("http://schemas.google.com/g/2005#home")) {
				if (p.getStreet() != null) {
					this.homeStreet = p.getStreet().getValue();
					if (this.homeStreet.contains("\n")) {
						this.homeStreet2 = this.homeStreet.substring(this.homeStreet.indexOf("\n") + 1);
						this.homeStreet  = this.homeStreet.substring(0, this.homeStreet.indexOf("\n"));
						if (this.homeStreet2.contains("\n")) {
							log.warning("More than one line in home street:" + this.lastName + " " + p.getStreet());
						}
					}
				}
				if (p.getCity() != null) {
					this.homeCity = p.getCity().getValue();
				}
				if (p.getRegion() != null) {
					this.homeState = p.getRegion().getValue();
				}
				if (p.getPostcode() != null) {
					this.homePostalCode = p.getPostcode().getValue();
				}
				if (p.getCountry() != null) {
					this.homeCountry = p.getCountry().getCode();//.getValue();
				}
			} else {
				log.warning("Unknown schema:" + p.getRel() + " " + p.getCity() + " " + p.getLabel() + " " + p.getPrimary());
			}
		}

		if (ce.getBirthday() != null) {
			this.birthday = ce.getBirthday().getValue();
		}

		for (Event e : ce.getEvents()) {
			if (e.getRel().equals("anniversary")) {
				this.anniversary = e.getWhen().getStartTime().toString();
			}
		}

		for (ExtendedProperty ep : ce.getExtendedProperties()) {
			if (ep.getName().equals(EP_HASH)) {
				this.hash = ep.getValue();
			}
			if (ep.getName().equals(EP_CONTACTSYNC)) {
				this.contactSync = ep.getValue();
			}
			if (ep.getName().equals(EP_CHILDREN)) {
				this.children = ep.getValue();
			}
			if (ep.getName().equals(EP_NOTES)) {
				this.notes = ep.getValue();
			}
		}
		this.ce = ce;
		//		if (checkHash() == false) {
		//			log.warning("Change to mail:" + this.lastName + " " + this.firstName);
		//		}
	}

	public Contact(String[] contactText, int i) {
		// TODO should this rely on column numbers
		this.lastName		= contactText[ 0];
		this.firstName		= contactText[ 1];
		//		this.business		= removeQuote(contactText[ 2]);
		//		this.home			= removeQuote(contactText[ 3]);
		//		this.mobile			= removeQuote(contactText[ 4]);
		//		this.mobile2		= removeQuote(contactText[ 5]);
		this.business		= contactText[ 2];
		this.home			= contactText[ 3];
		this.mobile			= contactText[ 4];
		this.mobile2		= contactText[ 5];
		this.emailAddress	= contactText[ 6];
		this.email2Address	= contactText[ 7];
		this.homeStreet		= contactText[ 8];
		this.homeStreet2	= contactText[ 9];
		this.homeCity		= contactText[10];
		this.homeState		= contactText[11];
		this.homePostalCode	= contactText[12];
		this.homeCountry	= contactText[13];
		this.birthday		= contactText[14]; //category
		this.anniversary	= contactText[15]; //notes
		this.category		= contactText[16]; //custon2
		this.children		= contactText[17]; //cs
		this.notes			= contactText[18]; //hash
		this.contactSync	= contactText[19]; //val
		this.hash			= contactText[20];
		this.validation		= contactText[21];
		this.row			= i;
		//		if (this.hash == null || this.hash.length() == 0) {
		//			this.hash = System."" + row;
		//		}
		//		if (hashCheck() == false) {
		//			log.warning("Change to docs:" + this.lastName + " " + this.firstName);
		//		}
	}

	// Creates property if not there
	// Deletes if no content
	// Updates existing otherwise
	private void addProperty(String property, String value, ContactEntry contact, HashMap<String, ExtendedProperty>properties) {
		if (value != null && value.length() > 0) {
			if (properties.containsKey(property)) {
				properties.get(property).setValue(value);
			} else {
				ExtendedProperty p = new ExtendedProperty();
				p.setName(property);
				p.setValue(value);
				contact.addExtendedProperty(p);
			}
		} else {
			if (properties.containsKey(property)) {
				contact.getExtendedProperties().remove(properties.get(property));
			}
		}
	}

	private int compare(String s1, String s2) {
		if (s1 == null || s2 == null) {
			return 0;
		}
		if (s1.equals(s2)) {
			return 1;
		}
		return 0;
	}

	public int countMatchingFields(Contact c) {
		int m = 0;
		m = m + compare(c.anniversary, this.anniversary);
		m = m + compare(c.birthday, this.birthday);
		m = m + compare(c.business, this.business);
		m = m + compare(c.category, this.category);
		m = m + compare(c.children, this.children);
		m = m + compare(c.emailAddress, this.emailAddress);
		m = m + compare(c.email2Address, this.email2Address);
		m = m + compare(c.firstName, this.firstName);
		m = m + compare(c.home, this.home);
		m = m + compare(c.homeCity, this.homeCity);
		m = m + compare(c.homeCountry, this.homeCountry);
		m = m + compare(c.homePostalCode, this.homePostalCode);
		m = m + compare(c.homeState, this.homeState);
		m = m + compare(c.homeStreet, this.homeStreet);
		m = m + compare(c.homeStreet2, this.homeStreet2);
		m = m + compare(c.lastName, this.lastName);
		m = m + compare(c.mobile, this.mobile);
		m = m + compare(c.mobile2, this.mobile2);
		m = m + compare(c.notes, this.notes);
		return m;
	}


	private String deNull(String s) {
		String r = "";
		if (s != null) {
			r = s;
		}
		return r;
	}

	//	private String diff(String s1, String s2) {
	//		if (s1 == null) {
	//			if (s2 == null) {
	//				return "";
	//			} else {
	//				return s2 + "\n";
	//			}
	//		} else {
	//			if (s2 == null) {
	//				return "-" + s1 + "\n";
	//			} else {
	//				if (!s1.equals(s2)) {
	//					return s2 + "\n";
	//				} else {
	//					return "";
	//				}
	//			}
	//		}
	//	}


	public String getAnniversary() {
		return anniversary;
	}

	public String getBirthday() {
		return birthday;
	}

	public String getBusiness() {
		return business;
	}

	public String getCategory() {
		return category;
	}

	public String getChildren() {
		return children;
	}

	public ContactEntry getContactEntry() {
		return this.ce;
	}

	public String getContactSync() {
		return contactSync;
	}

	/* Returns the difference text between this and the match */
	// TODO is this really the best place for this and storing the match in contact too - not sure that's the right design
	//	public String getDifference() {
	//		//		we are here
	//		//		why are things that are the same being reported as a difference
	//		//		e.g. see validation column on spreadsheet for examples
	//		StringBuffer d = new StringBuffer();
	//		if (this.match == null) {
	//			d.append("");
	//		} else {
	//			d.append(diff(this.anniversary, this.match.anniversary));
	//			d.append(diff(this.birthday, this.match.birthday));
	//			d.append(diff(this.business, this.match.business));
	//			d.append(diff(this.category, this.match.category));
	//			d.append(diff(this.children, this.match.children));
	//			d.append(diff(this.emailAddress, this.match.emailAddress));
	//			d.append(diff(this.email2Address, this.match.email2Address));
	//			d.append(diff(this.firstName, this.match.firstName));
	//			d.append(diff(this.home, this.match.home));
	//			d.append(diff(this.homeCity, this.match.homeCity));
	//			d.append(diff(this.homeCountry, this.match.homeCountry));
	//			d.append(diff(this.homePostalCode, this.match.homePostalCode));
	//			d.append(diff(this.homeState, this.match.homeState));
	//			d.append(diff(this.homeStreet, this.match.homeStreet));
	//			d.append(diff(this.homeStreet2, this.match.homeStreet2));
	//			d.append(diff(this.lastName, this.match.lastName));
	//			d.append(diff(this.mobile, this.match.mobile));
	//			d.append(diff(this.mobile2, this.match.mobile2));
	//			d.append(diff(this.notes, this.match.notes));
	//		}
	//		return d.toString();
	//	}

	//	public ContactEntry getContact(ContactGroupEntry group, ContactGroupEntry myContacts) {
	//		return updateContact(new ContactEntry(), group, myContacts);
	//	}

	public String getEmail2Address() {
		return email2Address;
	}

	public String getEmailAddress() {
		return emailAddress;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getHash() {
		return this.hash;
	}

	public String getHome() {
		return home;
	}

	public String getHomeCity() {
		return homeCity;
	}

	public String getHomeCountry() {
		return homeCountry;
	}

	public String getHomePostalCode() {
		return homePostalCode;
	}

	public String getHomeState() {
		return homeState;
	}

	public String getHomeStreet() {
		return homeStreet;
	}

	public String getHomeStreet2() {
		return homeStreet2;
	}

	public String getLastName() {
		return lastName;
	}

	public Contact getMatch() {
		return this.match;
	}

	public String getMobile() {
		return mobile;
	}

	public String getMobile2() {
		return mobile2;
	}

	public String getNotes() {
		return notes;
	}

	public int getRow() {
		return this.row;
	}

	public String getTextAddress() {
		String a = this.homeStreet		== null ? "" : this.homeStreet;
		String b = this.homeStreet2		== null ? "" : this.homeStreet2;
		String c = this.homeCity		== null ? "" : this.homeCity;
		String d = this.homeState		== null ? "" : this.homeState;
		String e = this.homePostalCode	== null ? "" : this.homePostalCode;
		String f = this.homeCountry		== null ? "" : this.homeCountry;
		return a + " " + b + " " + c + " " + d + " " + e + " " + f;
	}

	//	private ContactGroupEntry getSystemContactGroupEntry() {
	//		return this.myContacts;
	//	}

	public String getTextEmails() {
		String e = this.emailAddress == null ? "" : this.emailAddress;
		String f = this.email2Address == null ? "" : this.email2Address;
		return e + " " + f; // Space prevents e2 matching e1
		// TODO but we may want this to match unlike name
	}

	public String getTextHash() {
		return this.hash == null ? "" : this.hash;
	}

	/**
	 *
	 * @return First name Last name with null removed
	 */
	public String getTextNames() {
		String fn = this.firstName == null ? "" : this.firstName;
		String ln = this.lastName == null ? "" : this.lastName;
		return fn + " " + ln; // Space prevents first matching last
	}

	public String getTextPhones() {
		String h = this.home == null ? "" : this.home;
		String b = this.business == null ? "" : this.business;
		String m = this.mobile == null ? "" : this.mobile;
		String n = this.mobile2 == null ? "" : this.mobile2;
		return h + " " + b + " " + m + " " + n;
	}

	public String getValidation() {
		return validation;
	}

	public String hashCalc() {
		String hash = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			hash = Base64.encodeBase64String(md.digest(String.valueOf(hashString()).getBytes("UTF-8")));
		} catch (NoSuchAlgorithmException e) {
			log.severe("NoSuchAlgorithmException:" + e.getMessage());
		} catch (UnsupportedEncodingException e) {
			log.severe("UnsupportedEncodingException:" + e.getMessage());
		}
		return hash;
	}
	public boolean hashCheck() {
		boolean result = false;
		String hash = hashCalc();
		if (this.hash != null && this.hash.equals(hash)) {
			result = true;
		}
		return result;
	}

	private String hashString() {
		StringBuffer sb = new StringBuffer(deNull(this.lastName));
		sb.append(deNull(this.firstName));		sb.append(deNull(this.business));		sb.append(deNull(this.home));
		sb.append(deNull(this.mobile));			sb.append(deNull(this.mobile2));		sb.append(deNull(this.emailAddress));
		sb.append(deNull(this.email2Address));	sb.append(deNull(this.homeStreet));		sb.append(deNull(this.homeStreet2));
		sb.append(deNull(this.homeCity));		sb.append(deNull(this.homeState));		sb.append(deNull(this.homePostalCode));
		sb.append(deNull(this.homeCountry));	sb.append(deNull(this.birthday));		sb.append(deNull(this.anniversary));
		sb.append(deNull(this.category));
		sb.append(deNull(this.children));		sb.append(deNull(this.notes));			sb.append(deNull(this.contactSync));
		return sb.toString();
	}

	public void hashUpdate() {
		this.hash = hashCalc();
	}

	public void corrections() {
		if (this.getMobile() != null) {
			try {
				//						System.out.println(c.getMobile());
				com.google.i18n.phonenumbers.Phonenumber.PhoneNumber home = phoneUtil.parse(this.getMobile(), this.getHomeCountry());
				//						System.out.println(phoneUtil.format(home, PhoneNumberFormat.INTERNATIONAL));
			} catch (NumberParseException e) {
				//TODO this needs storing in the validation column
				System.out.println(e.getMessage());
			}
		}
		//	here
		//TODO do the matching, then the updating
		//TODO this validation and updates should be done in add contact so the hash is different and it updates the mail contacts
		//TODO set the validation to make clear where the new contact comes from
		//TODO set the validation with the results of validation
		//TODO clean up the telephone numbers
		//TODO make email all lower case
		//TODO validate correct country code is I18N country code
		//TODO correct birthday entries to be yyyymmdd
		//TODO maybe allow birthday to be mmdd(age) and replace (age) with year
		//TODO move email2 into empty email1
		//TODO same with mobile if mobile1 empty
	}

	/* Checked to make sure we can add to mail contact */
	public String isValid() {
		String result = "";
		// Must have a group
		if (this.category == null || this.category.length() == 0) {
			result = result + "|Category missing";
		}
		// Must have no errors
		if (this.validation != null && this.validation.length() > 0) {
			result = result + "|Has validation notes";
		}
		// Must have either last or first name
		if (this.firstName == null || this.firstName.length() == 0) {
			if (this.lastName == null || this.lastName.length() == 0) {
				result = result + "|Needs first and last name";
			} else {
				result = result + "|Needs first name";
			}
		} else {
			if (this.lastName == null || this.lastName.length() == 0) {
				result = result + "|Needs last name";
			}
		}
		if (result.length() == 0) {
			result = "|";
		}
		return result.substring(1);
	}

	//
	// TODO do we need to do this?
	//	private String removeQuote(String number) {
	//		String result = number;
	//		if (number != null && number.startsWith("'")) {
	//			result = number.substring(1);
	//		}
	//		return result;
	//	}

	//	public void updateContact(Contact c) {
	//		this.g = c.getGroup();
	//		this.ce = c.getContactEntry();
	//		this.myContacts = c.getSystemContactGroupEntry();
	//		updateContactEntry();
	//	}

	//
	//	public void setBusiness(String business) {
	//		this.business = business;
	//	}
	//
	//	public void setCategory(String category) {
	//		this.category = category;
	//	}
	//
	//	public void setChildren(String children) {
	//		this.children = children;
	//	}
	//
	//	public void setContactSync(String contactSync) {
	//		this.contactSync = contactSync;
	//	}
	//
	//	public void setEmail2Address(String email2Address) {
	//		this.email2Address = email2Address;
	//	}
	//
	//	public void setEmailAddress(String emailAddress) {
	//		this.emailAddress = emailAddress;
	//	}
	//
	//	public void setFirstName(String firstName) {
	//		this.firstName = firstName;
	//	}
	//
	//	public void setHash(String hash) {
	//		this.hash = hash;
	//	}
	//
	//	public void setHome(String home) {
	//		this.home = home;
	//	}
	//
	//	public void setHomeCity(String homeCity) {
	//		this.homeCity = homeCity;
	//	}
	//
	//	public void setHomeCountry(String homeCountry) {
	//		this.homeCountry = homeCountry;
	//	}
	//
	//	public void setHomePostalCode(String homePostalCode) {
	//		this.homePostalCode = homePostalCode;
	//	}
	//
	//	public void setHomeState(String homeState) {
	//		this.homeState = homeState;
	//	}
	//
	//	public void setHomeStreet(String homeStreet) {
	//		this.homeStreet = homeStreet;
	//	}
	//
	//	public void setHomeStreet2(String homeStreet2) {
	//		this.homeStreet2 = homeStreet2;
	//	}
	//
	//	public void setLastName(String lastName) {
	//		this.lastName = lastName;
	//	}
	//
	//	public void setMobile(String mobile) {
	//		this.mobile = mobile;
	//	}
	//
	//	public void setMobile2(String mobile2) {
	//		this.mobile2 = mobile2;
	//	}
	//
	//	public void setNotes(String notes) {
	//		this.notes = notes;
	//	}
	//
	//	public void setRow(int row) {
	//		this.row = row;
	//	}
	//	public void setValidation(String validation) {
	//		this.validation = validation;
	//	}
	//
	//	public String to1csv() {
	//		StringBuffer sb = new StringBuffer();
	//		sb.append(c(lastName));
	//		sb.append(c(firstName));
	//		sb.append(c(business));
	//		sb.append(c(home));
	//		sb.append(c(mobile));
	//		sb.append(c(mobile2));
	//		sb.append(c(emailAddress));
	//		sb.append(c(email2Address));
	//		sb.append(c(homeStreet));
	//		sb.append(c(homeStreet2));
	//		sb.append(c(homeCity));
	//		sb.append(c(homeState));
	//		sb.append(c(homePostalCode));
	//		sb.append(c(homeCountry));
	//		sb.append(c(birthday));
	//		sb.append(c(anniversary));
	//		sb.append(c(category));
	//		sb.append(c(children));
	//		sb.append(c(notes));
	//		sb.append(c(contactSync));
	//		sb.append(c(hash));
	//		sb.append(c(validation));
	//		sb.append(c("" + row));
	//		return sb.toString();
	//	}
	public void setContactEntry(ContactEntry ce) {
		this.ce = ce;
	}

	public void setContactGroupEntry(ContactGroupEntry g) {
		this.g = g;
	}

	public void setContactSync(String contactSync) {
		this.contactSync = contactSync;
	}

	public void updateContactSync(String contactSync) {
		if (this.contactSync == null) {
			this.contactSync = contactSync;
		} else {
			if (!this.contactSync.contains(contactSync)) {
				this.contactSync = this.contactSync + contactSync;
			}
		}
	}


	public void setMatch(Contact contact) {
		this.match = contact;
	}

	public void setRow(int r) {
		this.row = r;
	}

	public void setSystemContactGroupEntry(ContactGroupEntry myContacts) {
		this.myContacts = myContacts;
	}

	@Override
	public String toString() {
		return "[" + this.row + "|" + this.lastName + "|" + this.firstName + "|" + this.category + "|" + this.email2Address + "]";
		//		return "[" + this.row + " |" + this.lastName + "|" + this.firstName + "|" + this.hash + "|" + this.hashCalc() + "]";
	}

	public void updateContactEntry() {//ContactEntry contact, ContactGroupEntry group, ContactGroupEntry myContacts) {
		//		List<Event> events = contact.getEvents();
		//		if (events.size() > 0) {
		//			Event e = events.get(0);
		//			System.out.println(e.getLabel());
		//			System.out.println(e.getRel());
		//			System.out.println(e.getWhen().getRel());
		//			System.out.println(e.getWhen().getValueString());
		//			System.out.println(e.getWhen().getStartTime());
		//		}
		Name name = new Name();
		final String NO_YOMI = null;
		name.setFullName(new FullName(this.lastName + " " + this.firstName, NO_YOMI));
		name.setGivenName(new GivenName(this.firstName, NO_YOMI));
		if (this.lastName != null && this.lastName.length() > 0) {
			name.setFamilyName(new FamilyName(this.lastName, NO_YOMI));
		}
		this.ce.setName(name);

		this.ce.getEmailAddresses().clear();
		if (this.emailAddress != null && this.emailAddress.contains("@")) {
			Email primaryMail = new Email();
			primaryMail.setAddress(this.emailAddress);
			primaryMail.setRel("http://schemas.google.com/g/2005#home");
			primaryMail.setPrimary(true);
			this.ce.addEmailAddress(primaryMail);
		}

		if (this.email2Address != null && this.email2Address.contains("@")) {
			Email secondaryMail = new Email();
			secondaryMail.setAddress(this.email2Address);
			secondaryMail.setRel("http://schemas.google.com/g/2005#other");
			secondaryMail.setPrimary(false);
			this.ce.addEmailAddress(secondaryMail);
		}

		this.ce.getPhoneNumbers().clear();
		if (this.business != null && this.business.length() > 0) {
			PhoneNumber pBusiness = new PhoneNumber();
			pBusiness.setPhoneNumber(this.business);
			pBusiness.setPrimary(false);
			pBusiness.setRel("http://schemas.google.com/g/2005#work");
			this.ce.addPhoneNumber(pBusiness);
		}

		if (this.home != null && this.home.length() > 0) {
			PhoneNumber pHome = new PhoneNumber();
			pHome.setPhoneNumber(this.home);
			pHome.setPrimary(false);
			pHome.setRel("http://schemas.google.com/g/2005#home");
			this.ce.addPhoneNumber(pHome);
		}

		if (this.mobile != null && this.mobile.length() > 0) {
			PhoneNumber pMobile = new PhoneNumber();
			pMobile.setPhoneNumber(this.mobile);
			pMobile.setPrimary(false);
			pMobile.setRel("http://schemas.google.com/g/2005#mobile");
			this.ce.addPhoneNumber(pMobile);
		}

		if (this.mobile2 != null && this.mobile2.length() > 0) {
			PhoneNumber pMobile2 = new PhoneNumber();
			pMobile2.setPhoneNumber(this.mobile2);
			pMobile2.setPrimary(false);
			pMobile2.setRel("http://schemas.google.com/g/2005#mobile");
			this.ce.addPhoneNumber(pMobile2);
		}

		this.ce.getStructuredPostalAddresses().clear();
		StructuredPostalAddress aHome = new StructuredPostalAddress();
		if (this.homeStreet != null && this.homeStreet2 != null) {
			aHome.setStreet(new Street(this.homeStreet + "\n"
					+ this.homeStreet2));
		} else {
			if (this.homeStreet == null) {
				aHome.setStreet(new Street(this.homeStreet2));
			} else {
				aHome.setStreet(new Street(this.homeStreet));
			}
		}
		if (this.homeCity != null) {
			aHome.setCity(new City(this.homeCity));
		}
		if (this.homeState != null) {
			aHome.setRegion(new Region(this.homeState));
		}
		if (this.homePostalCode != null) {
			aHome.setPostcode(new PostCode(this.homePostalCode));
		}
		if (this.homeCountry != null) {
			aHome.setCountry(new Country(this.homeCountry, (new Locale("", this.homeCountry).getDisplayCountry())));
		}
		aHome.setPrimary(true);
		aHome.setRel("http://schemas.google.com/g/2005#home");
		this.ce.addStructuredPostalAddress(aHome);

		String content = "";
		if (this.children != null && this.children.length() > 0) {
			content = this.children;
		}
		if (this.notes != null && this.notes.length() > 0) {
			if (content.length() > 0) {
				content = content + "\n" + this.notes;
			} else {
				content = this.notes;
			}
		}
		// TODO are there other fields that don't get deleted if empty in docs
		//		log.info(lastName + " " + firstName + " " + "Content:" + content);
		if (content.length() > 0) {
			this.ce.setContent(new PlainTextConstruct(content));
		} else {
			this.ce.setContent(new PlainTextConstruct(""));
		}

		HashMap<String, ExtendedProperty>properties = new HashMap<String, ExtendedProperty>();
		for (ExtendedProperty p : this.ce.getExtendedProperties()) {
			properties.put(p.getName(), p);
		}

		addProperty(EP_CHILDREN, this.children, this.ce, properties);
		addProperty(EP_NOTES, this.notes, this.ce, properties);
		addProperty(EP_CONTACTSYNC, this.contactSync, this.ce, properties);
		addProperty(EP_HASH, this.hash, this.ce, properties);

		if (this.g != null) {
			GroupMembershipInfo groupMembershipInfo = new GroupMembershipInfo();
			groupMembershipInfo.setHref(this.g.getId());
			this.ce.getGroupMembershipInfos().add(groupMembershipInfo);
		}

		GroupMembershipInfo groupMembershipInfo1 = new GroupMembershipInfo();
		groupMembershipInfo1.setHref(myContacts.getId());
		this.ce.getGroupMembershipInfos().add(groupMembershipInfo1);

		//		contact.setBirthday(birthday)

		//		Event e = new Event();
		//		e.setRel(Event.Rel.ANNIVERSARY);
		//		e.setLabel("Test");
		//		e.setWhen(when)
		//
		//		contact.addEvent(new Event());
	}

	public void updateDetailsFrom(Contact dc) {
		this.anniversary = dc.getAnniversary();
		this.birthday = dc.getBirthday();
		this.business = dc.getBusiness();
		this.category = dc.getCategory();
		this.children = dc.getChildren();
		this.emailAddress = dc.getEmailAddress();
		this.email2Address = dc.getEmail2Address();
		this.firstName = dc.getFirstName();
		this.home = dc.getHome();
		this.homeCity = dc.getHomeCity();
		this.homeCountry = dc.getHomeCountry();
		this.homePostalCode = dc.getHomePostalCode();
		this.homeState = dc.getHomeState();
		this.homeStreet = dc.getHomeStreet();
		this.homeStreet2 = dc.getHomeStreet2();
		this.lastName = dc.getLastName();
		this.mobile = dc.getMobile();
		this.mobile2 = dc.getMobile2();
		this.notes = dc.getNotes();
		//TODO where is the best place to update the hash
		//TODO here and other places or in updatecontact entry only
		updateContactEntry();
	}

	/**
	 * Refreshes the error message - looses old errors
	 */
	public void updateError() {
		this.validation = isValid();
	}

	public void updateFromMatch() {
		// TODO do we need to update category differently?
		// TODO does this need to update the underlying contactentry
		// TODO call updateFromContact(this.match);
		this.anniversary	= this.match.getAnniversary();
		this.birthday		= this.match.getBirthday();
		this.business		= this.match.getBusiness();
		this.category		= this.match.getCategory();
		this.children		= this.match.getChildren();
		this.emailAddress	= this.match.getEmailAddress();
		this.email2Address	= this.match.getEmail2Address();
		this.firstName		= this.match.getFirstName();
		this.home			= this.match.getHome();
		this.homeCity		= this.match.getHomeCity();
		this.homeCountry	= this.match.getHomeCountry();
		this.homePostalCode	= this.match.getHomePostalCode();
		this.homeState		= this.match.getHomeState();
		this.homeStreet		= this.match.getHomeStreet();
		this.homeStreet2	= this.match.getHomeStreet2();
		this.lastName		= this.match.getLastName();
		this.mobile			= this.match.getMobile();
		this.mobile2		= this.match.getMobile2();
		this.notes			= this.match.getNotes();
		//This is needed to make hash match next time match is called
		this.contactSync	= this.match.getContactSync();
	}

	public void setHash(String hash) {
		this.hash = hash;
	}

	// TODO should addGroup, modGroup etc. be an interface method in the store?
	public void addGroup(String group) {
		if (this.category != null && this.category.length() > 0) {
			log.warning("Overwriting category:" + this.category + "->" + group);
		}
		this.category = group;
	}
}
